#pragma once
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cassert>
using namespace std;
namespace xzq
{
    class string
    {
    public:
        typedef char *iterator;
        iterator begin()
        {
            return _str;
        }
        iterator end()
        {
            return _str + _size;
        }
        string(const char *str = "")
        {
            _size = strlen(str);
            _capacity = _size;
            _str = new char[_capacity + 1];
            strcpy(_str, str);
        }
        void swap(string &s)
        {
            ::swap(_str, s._str);
            ::swap(_size, s._size);
            ::swap(_capacity, s._capacity);
        }
        string(const string &s)
            : _str(nullptr), _size(0), _capacity(0)
        {
            string tmp(s._str);
            swap(tmp);
        }
        string &operator=(string s)
        {
            swap(s);
            return *this;
        }
        ~string()
        {
            delete[] _str;
            _str = nullptr;
            _size = _capacity = 0;
        }
        size_t size() const
        {
            return _size;
        }
        size_t capacity() const
        {
            return _capacity;
        }
        char &operator[](size_t i)
        {
            assert(i < _size);
            return _str[i];
        }
        const char &operator[](size_t i) const
        {
            assert(i < _size);
            return _str[i];
        }
        const char *c_str()
        {
            return _str;
        }
        void reserve(size_t n)
        {
            if (n > _capacity)
            {
                char *newstr = new char[n + 1];
                strcpy(newstr, _str);
                delete[] _str;
                _str = newstr;
                _capacity = n;
            }
        }
        void resize(size_t n, char ch = '\0')
        {
            if (n < _size)
            {
                _str[n] = '\0';
                _size = n;
            }
            else
            {
                if (n > _capacity)
                {
                    reserve(n);
                }
                for (size_t i = _size; i < n; i++)
                {
                    _str[i] = ch;
                }
                _size = n;
                _str[_size] = '\0';
            }
        }
        void insert(size_t pos, char ch)
        {
            assert(pos <= _size);
            if (_size == _capacity)
            {
                size_t newcapacity = _capacity == 0 ? 2 : 2 * _capacity;
                reserve(newcapacity);
            }
            int end = _size;
            while (end >= (int)pos)
            {
                _str[end + 1] = _str[end];
                --end;
            }
            _str[pos] = ch;
            ++_size;
        }
        string &insert(size_t pos, const char *str)
        {
            assert(pos <= _size);
            size_t len = strlen(str);
            if (_size + len > _capacity)
            {
                reserve(_size + len);
            }
            int end = _size;
            while (end >= (int)pos)
            {
                _str[end + len] = _str[end];
                --end;
            }
            strncpy(_str + pos, str, len);
            _size += len;
            return *this;
        }
        void push_back(char ch)
        {
            insert(_size, ch);
        }
        void append(const char *str)
        {
            insert(_size, str);
        }
        string &operator+=(const char *str)
        {
            append(str);
            return *this;
        }
        string &operator+=(char ch)
        {
            push_back(ch);
            return *this;
        }
        string &erase(size_t pos, size_t len = npos)
        {
            assert(pos < _size);
            if (len >= _size - pos)
            {
                _str[pos] = '\0';
                _size = pos;
            }
            else
            {
                size_t i = pos + len;
                while (i <= _size)
                {
                    _str[i - len] = _str[i];
                    i++;
                }
                _size -= len;
            }
            return *this;
        }
        size_t find(char ch, size_t pos = 0)
        {
            for (size_t i = pos; i < _size; i++)
            {
                if (_str[i] == ch)
                {
                    return i;
                }
            }
            return npos;
        }
        size_t find(const char *str, size_t pos = 0)
        {
            char *p = strstr(_str + pos, str);
            if (p == nullptr)
            {
                return npos;
            }
            else
            {
                return p - _str;
            }
        }
        bool operator<(const string &s)
        {
            int ret = strcmp(_str, s._str);
            return ret < 0;
        }
        bool operator==(const string &s)
        {
            int ret = strcmp(_str, s._str);
            return ret == 0;
        }
        bool operator<=(const string &s)
        {
            return *this < s || *this == s;
        }
        bool operator>(const string &s)
        {
            return !(*this <= s);
        }
        bool operator>=(const string &s)
        {
            return !(*this < s);
        }
        bool operator!=(const string &s)
        {
            return !(*this == s);
        }

    private:
        char *_str;
        size_t _size;
        size_t _capacity;
        static size_t npos;
    };
    size_t string::npos = -1;
    ostream &operator<<(ostream &_cout, const string &s)
    {
        for (size_t i = 0; i < s.size(); i++)
        {
            _cout << s[i];
        }
        return _cout;
    }
    istream &operator>>(istream &_cin, string &s)
    {
        while (1)
        {
            char ch;
            ch = _cin.get();
            if (ch == ' ' || ch == '\n')
            {
                break;
            }
            else
            {
                s += ch;
            }
        }
        return _cin;
    }
    void test()
    {
        string s("hello bit");
        string::iterator it = s.begin();
        while(it != s.end())
        {
            cout<<*it;
            ++it;
        }
        cout<<endl;
        for(size_t i = 0;i < s.size();i++)
        {
            cout<<s[i];
        }
        cout<<endl;
        for(auto ch : s)
        {
            cout<<ch;
        }
        cout<<endl;
    }
}